#include "CHIP_PIN_module/CHIP_PIN.hpp"

#ifdef DBG_TAG
#undef DBG_TAG
#endif
#ifdef DBG_LVL
#undef DBG_LVL
#endif

#define DBG_TAG     "CHIP_PIN"
#define DBG_LVL     DBG_LOG

extern "C"
{
#include <rtdbg.h>
}

using namespace std;



/******************************************************************************
 *
 * @brief:     CHIP_INPUT_PIN类实现
 *
 ******************************************************************************/
CHIP_INPUT_PIN::CHIP_INPUT_PIN(rt_base_t pin_num,
                               chip_input_pin_mode pin_mode,
                               chip_input_pin_pull_mode pin_pull_mode,
                               void (*pin_interrupt_handler)(void *handler_args),
                               void *handler_args)
{
    this->pin_num = pin_num;
    this->pin_mode = pin_mode;

    switch (pin_pull_mode)
    {
    case chip_input_pin_pull_mode_up:
        rt_pin_mode(pin_num, PIN_MODE_INPUT_PULLUP);
        break;
    case chip_input_pin_pull_mode_down:
        rt_pin_mode(pin_num, PIN_MODE_INPUT_PULLDOWN);
        break;
    case chip_input_pin_pull_mode_none:
        rt_pin_mode(pin_num, PIN_MODE_INPUT);
        break;
    default:
        break;
    }

    switch (pin_mode)
    {
    case chip_input_pin_mode_interrupt_rising_active:
        if (!pin_interrupt_handler)
        {
            LOG_E("error:input pin <%d> interrupt mode should have hanlder function", pin_num);
            goto end;
        }
        if (rt_pin_attach_irq(pin_num, PIN_IRQ_MODE_RISING, pin_interrupt_handler, handler_args) != RT_EOK)
        {
            LOG_E("error:input pin <%d> set interrupt hanlder function error", pin_num);
            goto end;
        }
        break;
    case chip_input_pin_mode_interrupt_falling_active:
        if (!pin_interrupt_handler)
        {
            LOG_E("error:input pin <%d> interrupt mode should have hanlder function", pin_num);
            goto end;
        }
        if (rt_pin_attach_irq(pin_num, PIN_IRQ_MODE_FALLING, pin_interrupt_handler, handler_args) != RT_EOK)
        {
            LOG_E("error:input pin <%d> set interrupt hanlder function error", pin_num);
            goto end;
        }
        break;
    case chip_input_pin_mode_interrupt_rising_falling_active:
        if (!pin_interrupt_handler)
        {
            LOG_E("error:input pin <%d> interrupt mode should have hanlder function", pin_num);
            goto end;
        }
        if (rt_pin_attach_irq(pin_num,
        PIN_IRQ_MODE_RISING_FALLING,
                              pin_interrupt_handler, handler_args) != RT_EOK)
        {
            LOG_E("error:input pin <%d> set interrupt hanlder function error", pin_num);
            goto end;
        }
        break;
    case chip_input_pin_mode_interrupt_high_active:
        if (!pin_interrupt_handler)
        {
            LOG_E("error:input pin <%d> interrupt mode should have hanlder function", pin_num);
            goto end;
        }
        if (rt_pin_attach_irq(pin_num, PIN_IRQ_MODE_HIGH_LEVEL, pin_interrupt_handler, handler_args) != RT_EOK)
        {
            LOG_E("error:input pin <%d> set interrupt hanlder function error", pin_num);
            goto end;
        }
        break;
    case chip_input_pin_mode_interrupt_low_active:
        if (!pin_interrupt_handler)
        {
            LOG_E("error:input pin <%d> interrupt mode should have hanlder function", pin_num);
            goto end;
        }
        if (rt_pin_attach_irq(pin_num, PIN_IRQ_MODE_LOW_LEVEL, pin_interrupt_handler, handler_args) != RT_EOK)
        {
            LOG_E("error:input pin <%d> set interrupt hanlder function error", pin_num);
            goto end;
        }
        break;
    default:
        break;
    }
    LOG_I("input pin <%d> create ok", pin_num);
    init_flag = chip_pin_status_ok;
    return;
    end:
    LOG_E("input pin <%d> create fail", pin_num);
    init_flag = chip_pin_status_fail;
    return;
}
CHIP_INPUT_PIN::~CHIP_INPUT_PIN()
{

}

/*中断模式使用*/
chip_pin_status CHIP_INPUT_PIN::CHIP_INPUT_PIN_irq_enable()
{
    if (init_flag != chip_pin_status_ok)
    {
        LOG_E("error:input pin <%d> init not ok,pls check", pin_num);
        return chip_pin_status_fail;
    }

    if (pin_mode == chip_input_pin_mode_simple)
    {
        LOG_E("error:input pin <%d> simple mode isn't allow to call this function", pin_num);
        return chip_pin_status_fail;
    }

    if (rt_pin_irq_enable(pin_num, PIN_IRQ_ENABLE) != RT_EOK)
    {
        LOG_E("error:input pin <%d> simple mode isn't allow to call this function", pin_num);
        return chip_pin_status_fail;
    }
    return chip_pin_status_ok;
}
chip_pin_status CHIP_INPUT_PIN::CHIP_INPUT_PIN_irq_disable()
{
    if (init_flag != chip_pin_status_ok)
    {
        LOG_E("error:input pin <%d> init not ok,pls check", pin_num);
        return chip_pin_status_fail;
    }

    if (pin_mode == chip_input_pin_mode_simple)
    {
        LOG_E("error:input pin <%d> simple mode isn't allow to call this function", pin_num);
        return chip_pin_status_fail;
    }
    if (rt_pin_irq_enable(pin_num, PIN_IRQ_DISABLE) != RT_EOK)
    {
        LOG_E("error:input pin <%d> simple mode isn't allow to call this function", pin_num);
        return chip_pin_status_fail;
    }
    return chip_pin_status_ok;

}

chip_input_pin_mode CHIP_INPUT_PIN::CHIP_INPUT_PIN_read_pin_mode()
{
    return pin_mode;
}


/*简单模式使用*/
chip_pin_level CHIP_INPUT_PIN::CHIP_INPUT_PIN_read()
{
    if (init_flag != chip_pin_status_ok)
    {
        LOG_E("error:input pin <%d> init not ok,pls check", pin_num);
        return chip_pin_level_ERROR;
    }

    if (rt_pin_read(pin_num) == PIN_LOW)
        return chip_pin_level_LOW;
    else
        return chip_pin_level_HIGH;
}

chip_pin_status CHIP_INPUT_PIN::CHIP_INPUT_PIN_read_init_status()
{
    return this->init_flag;
}
/******************************************************************************
 *
 * @brief:     CHIP_OUTPUT_PIN类实现
 *
 ******************************************************************************/
CHIP_OUTPUT_PIN::CHIP_OUTPUT_PIN(rt_base_t pin_num,
                                 chip_output_pin_out_mode pin_out_mode,
                                 chip_pin_level default_level)
{
    this->pin_num = pin_num;
    switch (pin_out_mode)
    {
    case chip_output_pin_out_mode_od:
        rt_pin_mode(pin_num, PIN_MODE_OUTPUT_OD);
        break;
    case chip_output_pin_out_mode_normal:
        rt_pin_mode(pin_num, PIN_MODE_OUTPUT);
        break;
    default:
        break;
    }

    pin_level_lock = rt_mutex_create(("<" + to_string(pin_num) + ">").c_str(), RT_IPC_FLAG_PRIO);
    if (!pin_level_lock)
    {
        LOG_E("error:output pin <%d> create lock fail", pin_num);
        goto end;
    }

    if (default_level == chip_pin_level_LOW)
    {
        rt_pin_write(pin_num, PIN_LOW);
        rt_mutex_take(pin_level_lock, RT_WAITING_FOREVER);
        pin_level = chip_pin_level_LOW;
        rt_mutex_release(pin_level_lock);
    }
    else
    {
        rt_pin_write(pin_num, PIN_HIGH);
        rt_mutex_take(pin_level_lock, RT_WAITING_FOREVER);
        pin_level = chip_pin_level_HIGH;
        rt_mutex_release(pin_level_lock);
    }

    LOG_I("output pin <%d> init ok", pin_num);
    init_flag = chip_pin_status_ok;
    return;
    end:
    LOG_E("output pin <%d> init fail", pin_num);
    init_flag = chip_pin_status_fail;
    return;
}

CHIP_OUTPUT_PIN::~CHIP_OUTPUT_PIN()
{

}

//返回PIN_LOW或PIN_HIGH
chip_pin_level CHIP_OUTPUT_PIN::CHIP_OUTPUT_PIN_read()
{
    chip_pin_level back_level;
    if (init_flag != chip_pin_status_ok)
    {
        LOG_E("error:output pin <%d> init not ok,pls check", pin_num);
        return chip_pin_level_ERROR;
    }
    rt_mutex_take(pin_level_lock, RT_WAITING_FOREVER);
    back_level = pin_level;
    rt_mutex_release(pin_level_lock);

    return back_level;

}
void CHIP_OUTPUT_PIN::CHIP_OUTPUT_PIN_write(chip_pin_level write_level)
{
    if (init_flag != chip_pin_status_ok)
    {
        LOG_E("error:output pin <%d> init not ok,pls check", pin_num);
        return;
    }

    if (write_level == chip_pin_level_LOW)
    {
        rt_pin_write(pin_num, PIN_LOW);
        rt_mutex_take(pin_level_lock, RT_WAITING_FOREVER);
        pin_level = chip_pin_level_LOW;
        rt_mutex_release(pin_level_lock);
    }
    else
    {
        rt_pin_write(pin_num, PIN_HIGH);
        rt_mutex_take(pin_level_lock, RT_WAITING_FOREVER);
        pin_level = chip_pin_level_HIGH;
        rt_mutex_release(pin_level_lock);
    }
}

chip_pin_status CHIP_OUTPUT_PIN::CHIP_OUTPUT_read_init_status()
{
    return this->init_flag;
}
